package com.guan.core;

import com.guan.core.entity.BeanEntity;
import com.guan.core.entity.Property;
import com.guan.entity.AdminUser;
import com.guan.core.util.Contants;
import com.guan.core.util.XMLUtil;
import org.dom4j.Document;
import org.dom4j.Element;

import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * bean容器类  --不是注解的实现
 * Created by Administrator on 2018/1/9 0009.
 */
@SuppressWarnings("all")
public class ApplicationContext {
	// 存放单列的实例bean对象
	private Map<String, Object> beans = new HashMap<String, Object>();
	// 存放多例的实例bean对象
	private Map<String, BeanEntity> propertys = new HashMap<String, BeanEntity>();

	public ApplicationContext(String xml) {
		XMLUtil.log("*****bean容器框架开始初始化***********");
		Document doc = XMLUtil.getDocFromFile(ApplicationContext.class.getClassLoader().getResourceAsStream(xml));
		Element root = XMLUtil.getRootElement(doc);
		List<Element> beas = XMLUtil.getChildElements(root);
		try {
			for (Element bea : beas) {
				String id = bea.attributeValue("id");
				String scope = bea.attributeValue("scope");
				String className = bea.attributeValue("class");
				System.out.println(id+"开始解析");
				BeanEntity bean = null;
				Class clazz = Class.forName(className);
				Object instance = null;//单例得实例对象
				// 判断是单例还是多例
				if (null != scope && scope.equals(Contants.PROTO_STR)) {
					bean = new BeanEntity();
					bean.setId(id);
					bean.setClassName(className);
					bean.setScope(scope);
					propertys.put(id, bean);
				}else {
					instance = clazz.newInstance();
					beans.put(id, instance);
				}
				// 迭代bean的所有property属性 初始化操作
				for (Object obj : bea.elements()) {
					Element property = (Element) obj;
					String name = property.attributeValue("name");
					String value = property.attributeValue("value");
					String ref = property.attributeValue("ref");
					if (null != bean) {// 代表prototype 多例
						Property pro = new Property();
						pro.setName(name);
						pro.setRef(ref);
						pro.setValue(value);
						bean.addProperty(pro);
					} else {// 单例的 初始化的时候就应该创建好实例
						//通过反射拿到所有的属性
						Field field = clazz.getDeclaredField(name);
						//开放修改权限
						field.setAccessible(true);
						if(null == value) {
							field.set(instance, getBean(ref));
						}else {
							field.set(instance, value);
						}
					}
				}

			}
		} catch (Exception e1) {
			e1.printStackTrace();
		}
		XMLUtil.log("*****bean容器框架开始初始化完成***********");
	}
	/**
	 * 通过id拿到一个java实例
	 * @param id
	 * @return
	 */
	public Object getBean(String id) {
		//先通过单例拿
		Object instance = beans.get(id);
		if(null == instance) {
			//通过原型去拿
			BeanEntity b = propertys.get(id);
			try {
				Class<?> clazz = Class.forName(b.getClassName());
			    instance = clazz.newInstance();
			    for(Property pro:b.getProps()) {
			    	//通过反射拿到所有的属性
					Field field = clazz.getDeclaredField(pro.getName());
					//开放修改权限
					field.setAccessible(true);
					if(null == pro.getValue()) {//代表有引用别的实体类
						//递归调用，别的ref代表别的bean的id
						field.set(instance, getBean(pro.getRef()));
					}else {
						field.set(instance, pro.getValue());
					}
			    }
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
 		}
		return instance;
	}
	public static void main(String[] args) {
		ApplicationContext a = new ApplicationContext("beans.xml");
		AdminUser user = (AdminUser) a.getBean("user");
		AdminUser user2 = (AdminUser) a.getBean("user");
		//判断多列还是 单例
		System.out.println(user.getUserId()+"--"+user.getAge()+"--"+user.getUserName()+user.getJdbcBaseDao());
		System.out.println(user2.getUserId()+"--"+user2.getAge()+"--"+user2.getUserName());
		System.err.println(user==user2);
	}
}
